<!-- 组织信息 -->
<template>
  <div class="">
    <el-row :gutter="10">
      <el-col :span="6">
        <el-card class="box-card">
          <el-input placeholder="输入关键字进行过滤" v-model.trim="filterText"> </el-input>
          <el-tree class="filter-tree" :load="loadNode" :props="defaultProps" :filter-node-method="filterNode" :expand-on-click-node="false" node-key="id" :default-expanded-keys="state.defaultExpandedKeys" highlight-current lazy @node-click="handleNodeClick" ref="treeRef">
            <template #default="{ node, data }">
              <span class="custom-tree-node">
                <span>{{ node.label }}</span>
                <span>
                  <el-button type="primary" text v-if="node.level !== 2" @click.stop="handleAppend(node, data)">新增</el-button>
                  <el-button text class="red ml0" v-if="node.level !== 1" @click.stop="handleRemove(node, data)">删除</el-button>
                </span>
              </span>
            </template>
          </el-tree>
        </el-card>
      </el-col>
      <el-col :span="18">
        <el-card class="box-card">
          <el-form label-width="120px" :model="organizationForm" :rules="rules" :highlight-current="true" v-loading="loadingDialog" ref="formRef">
            <el-row :gutter="10">
              <el-col :span="7">
                <el-form-item label="组织名称：" prop="name">
                  <el-input v-model.trim="organizationForm.name" placeholder="点击左侧新增后添加组织名称"></el-input>
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>
          <el-row :gutter="10">
            <el-col :span="6" :offset="1">
              <el-button type="primary" :icon="Check" :disabled="disabledbtn" @click="submitForm">保存</el-button>
            </el-col>
          </el-row>
          <el-row :gutter="10">
            <el-col :span="20" :offset="1">
              <ul>
                <li>描述：用于描述公司的组织架构（或公司的部门）</li>
              </ul>
            </el-col>
          </el-row>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>
<script setup lang="ts" name="organizationInfo">
import { reactive, ref, watch } from "vue";
import { ElMessage, ElMessageBox, type TreeInstance, type TreeNodeData } from "element-plus";
import { Check } from "@element-plus/icons-vue";
import type { IOrganizationDTO, IOrganizationVO } from "@/types/organization";
import type Node from "element-plus/es/components/tree/src/model/node";
import { commonOrganizationInfo, deleteOrganizationInfo, getOrganizationInfo } from "@/utils/api/organization";
import type { postOrPutType } from "@/constants";

const state = reactive({
  defaultExpandedKeys: [0] /* 默认显示哪几级信息 */
});
const filterText = ref("");
const treeRef = ref<TreeInstance>();
const formRef = useTemplateRef("formRef");
const defaultProps = reactive({
  children: "children",
  label: "name",
  isLeaf: "leaf"
});

const methodType = ref<postOrPutType>("POST"); /* 请求类型 */

const organizationForm = reactive<IOrganizationDTO>({
  id: 0,
  name: ""
});
const rules = {
  name: [{ required: true, message: "请填写组织名称", trigger: "blur" }]
};

const delVisibleType = ref("delete"); /* 删除类型（单选，多选） */
const loadingDialog = ref(false); /* */
const disabledbtn = ref(false); /* 可用与不可用 */
const node_had = ref<Node>();
const isParent = ref(true); /* */
const id = ref(0);

/* 过滤节点信息 */
/* 过滤节点信息 */
const filterNode = (value: string, data: TreeNodeData) => {
  if (!value) return true;
  return data.name.indexOf(value) !== -1;
};

/* 更新tree中某个结点 */
const handleUpdateTree = () => {
  // 通过ID利用DOM找到该结点
  const node = treeRef.value?.getNode(node_had.value!.data);
  const tempNode = isParent.value ? node?.parent : node;
  // 更改该结点属性（重要）
  if (tempNode) {
    tempNode.loaded = false;
    // 手动调用该结点数据加载方法
    tempNode.loadData(() => {});
  }
};
/* 点击获取节点信息 */
const handleNodeClick = (data: IOrganizationDTO, node: Node) => {
  node_had.value = node;
  isParent.value = true;
  organizationForm.id = data.id;
  organizationForm.name = data.name;
  if (data.id !== -1) {
    /* 修改 */
    methodType.value = "PUT";
  } else {
    /* 新增 */
    methodType.value = "POST";
  }
};
/* 数据初始化 */
const handleInitData = () => {
  methodType.value = "POST";
  organizationForm.id = 0;
  organizationForm.name = "";
};
/* 添加节点 */
const handleAppend = (node: Node, data: IOrganizationVO) => {
  if (!node.loaded) {
    ElMessage.warning(`请先点击左侧小箭头，加载下级，再进行新增下级操作`);
    return;
  }
  isParent.value = false;
  const childNodes = node.childNodes;
  for (let i = 0; i < childNodes.length; i++) {
    if (childNodes[i].data.id === "") return;
  }
  const newChild = {
    id: -1,
    name: "",
    leaf: true,
    children: []
  };

  if (!data.children) {
    data.children = [];
  }
  data.children.push(newChild);

  node_had.value = node;
  handleInitData();
};
/* 删除节点 */
const handleRemove = (node: Node, data: IOrganizationDTO) => {
  isParent.value = true;
  if (data.id === -1) {
    const parent = node.parent;
    const children = parent.data.children || parent.data;
    const index = children.findIndex((d: IOrganizationDTO) => d.id === data.id);
    children.splice(index, 1);
    node.parent.loaded = false;
    node.parent.loadData(() => {});
    handleInitData();
  } else {
    id.value = data.id;
    /* 发送请求id 去删除数据 */
    delVisibleType.value = "delete";
    deleteMessageBox();
  }
};
/* 加载节点数据 */
const loadNode = async (node: Node, resolve: (data: IOrganizationDTO[]) => void) => {
  node_had.value = node;
  if (node.level === 0) {
    const data: IOrganizationVO = {
      id: 0,
      name: "组织管理",
      children: [],
      leaf: true
    };
    return resolve([data]);
  }
  try {
    const res = await getOrganizationInfo<Array<IOrganizationVO>>();
    if (res.status === 1 && res.result.length !== 0) {
      res.result.forEach(item => {
        item.leaf = true;
        item.children = [];
      });
      return resolve(res.result);
    }
    return resolve([]);
  } catch (error) {
    console.log(error);
    return resolve([]);
  }
};
/* 保存或编辑 */
const submitForm = () => {
  if (isParent.value && node_had.value?.data && node_had.value.data.id === 0) {
    ElMessage.warning(`'组织管理'目录不能修改，点击左侧新增今天添加组织`);
    return;
  }
  if (!formRef.value) return;
  formRef.value.validate(valid => {
    if (!valid) {
      ElMessage.warning("请填写必填字段");
      return;
    }
    submitFormInfo();
  });
};
/* 保存或编辑信息 */
const submitFormInfo = () => {
  /* 防止多次提交 */
  disabledbtn.value = true;
  loadingDialog.value = true;
  commonOrganizationInfo(organizationForm, methodType.value)
    .then(res => {
      ElMessage.success(res.msg);
      handleUpdateTree();
      handleInitData();
    })
    .catch(() => {})
    .finally(() => {
      disabledbtn.value = false;
      loadingDialog.value = false;
    });
};
/* 打开删除弹框 */
const deleteMessageBox = () => {
  ElMessageBox.confirm("删除不可恢复，是否确定删除?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(() => {
      deleteInfo([id.value]);
    })
    .catch(() => {
      ElMessage.info("已取消删除");
    });
};
/* 删除后的信息 */
const deleteInfo = (idArray: Array<number>) => {
  disabledbtn.value = true;
  deleteOrganizationInfo({ idArray })
    .then(() => {
      handleUpdateTree();
      handleInitData();
      ElMessage.success(`删除数据成功`);
    })
    .catch(() => {})
    .finally(() => {
      disabledbtn.value = false;
    });
};

/* 监听筛选数据 */
watch(filterText, val => {
  treeRef.value?.filter(val);
});
</script>

<style scoped>
.el-row {
  margin-bottom: 15px;
}

.el-col {
  border-radius: 4px;
}

.bg-purple-dark {
  background: #99a9bf;
}

.bg-purple {
  background: #d3dce6;
}

.bg-purple-light {
  background: #e5e9f2;
}

.grid-content {
  border-radius: 4px;
  min-height: 36px;
}

.row-bg {
  padding: 10px 0;
  background-color: #f9fafc;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

/* 提示图标设置 */
.icon-wzg-config {
  height: 30px;
  line-height: 30px;
}

.el-tree {
  height: 740px;
  overflow: scroll;
}

.red {
  color: #f00;
}

:deep(.el-tree-node__label) {
  width: 100%;
}

.ml0 {
  margin-left: 0;
}
</style>
